<!DOCTYPE html>
<html lang="en">
<head>
		<title>SKiDL &mdash; Good Things Come In Packages!</title>
		<meta charset="utf-8" />
		<link rel="profile" href="http://gmpg.org/xfn/11" />
		<link rel="stylesheet" type="text/css" href="/skidl/theme/css/style.css" />
		<link rel='stylesheet' id='oswald-css'  href='http://fonts.googleapis.com/css?family=Oswald&#038;ver=3.3.2' type='text/css' media='all' />
		<link rel="preconnect" href="https://fonts.googleapis.com">
		<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
		<link href="https://fonts.googleapis.com/css2?family=Oswald&family=Roboto+Condensed&display=swap" rel="stylesheet">
		<!-- <style type="text/css">
			body.custom-background { background-color: #f5f5f5; }
		</style> -->
		<link rel="alternate" type="application/atom+xml"
			title="SKiDL — Flux Atom"
			href="/skidl/" />
		<!--[if lte IE 8]><script src="/skidl/theme/js/html5shiv.js"></script><![endif]-->
</head>

<body class="home blog custom-background " >
	<div id="container">
		<div id="header">
				<h1 id="site-title"><a href="/skidl"><img src="/skidl/images/banner.png" width="100%"></a></h1>
				<!-- <h1 id="site-title"><a href="/skidl">SKiDL</a></h1> -->
		</div><!-- /#banner -->

		<div id="menu">
			<div class="menu-navigation-container">
				<ul id="menu-navigation" class="menu">
						<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="https://github.com/devbisme/skidl">Github</a></li>
						<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="https://github.com/devbisme/skidl/discussions">Forum</a></li>
						<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="/skidl/category/posts.html">Blog</a></li>
						<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="/skidl/api/html/index.html">API</a></li>
						<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="/skidl/">Home</a></li>

				</ul>
			</div> <!--/#menu-navigation-container-->
		</div><!-- /#menu -->

		<div class="page-title">
		</div>

		<div id="contents">

<div class="post type-post status-publish format-standard hentry category-general" id="post">
	<div class="entry-meta">
		<span class="date"><a href="/skidl/package-decorator-2020-05-27.html">Wed 27 May 2020</a></span>
		/
		<span class="byline"><a href="/skidl/author/dave-vandenbout.html">Dave Vandenbout</a></span>
	</div> <!-- /#entry-meta -->
	<div class="main">
		<h2 class="entry-title">
			<a href="/skidl/package-decorator-2020-05-27.html" title="Permalink to Good Things Come In Packages!" rel="bookmark">Good Things Come In Packages!</a>
		</h2>
		<div class="entry-content">
			<p>Up to now, SKiDL supported hierarchy by applying the <code>@subcircuit</code> decorator to a Python function:</p>
<div class="highlight"><pre><span></span><code><span class="nd">@subcircuit</span>
<span class="k">def</span> <span class="nf">analog_average</span><span class="p">(</span><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span><span class="p">):</span>
<span class="w">    </span><span class="sd">&quot;&quot;&quot;Output the average of the two inputs.&quot;&quot;&quot;</span>

    <span class="c1"># Create two 1K resistors.</span>
    <span class="n">r1</span><span class="p">,</span> <span class="n">r2</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">Part</span><span class="p">(</span><span class="s1">&#39;Device&#39;</span><span class="p">,</span> <span class="s1">&#39;R&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;1K&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>

    <span class="c1"># Each input connects thru a resistor to the avg output.</span>
    <span class="n">r1</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in1</span><span class="p">,</span> <span class="n">avg</span>
    <span class="n">r2</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span>
</code></pre></div>

<p>Then this subcircuit is instantiated by calling the function with nets
passed as arguments:</p>
<div class="highlight"><pre><span></span><code><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">in3</span><span class="p">,</span> <span class="n">in4</span><span class="p">,</span> <span class="n">out1</span><span class="p">,</span> <span class="n">out2</span> <span class="o">=</span> <span class="n">Net</span><span class="p">()</span><span class="o">*</span><span class="mi">6</span>  <span class="c1"># Make some I/O nets.</span>

<span class="n">analog_average</span><span class="p">(</span><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">out1</span><span class="p">)</span>  <span class="c1"># One instantiation of the averager.</span>

<span class="o">...</span> <span class="n">Some</span> <span class="n">more</span> <span class="n">code</span> <span class="o">...</span>

<span class="n">analog_average</span><span class="p">(</span><span class="n">in3</span><span class="p">,</span> <span class="n">in4</span><span class="p">,</span> <span class="n">out2</span><span class="p">)</span>  <span class="c1"># A second instantiation.</span>
</code></pre></div>

<p>It was <a href="https://github.com/devbisme/skidl/issues/48">pointed out</a> that this method
of instantiating subcircuits is quite different from what is used for parts.
Unlike the connections to a subcircuit that are all made at a single place when the
function is called, the connections to a part can be placed
at various, non-contiguous locations in the code:</p>
<div class="highlight"><pre><span></span><code><span class="n">q_npn</span> <span class="o">=</span> <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s2">&quot;Q_NPN_BCE&quot;</span><span class="p">)</span>  <span class="c1"># Instantiate a transistor.</span>

<span class="o">...</span>

<span class="n">q_npn</span><span class="p">[</span><span class="s1">&#39;E&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">Net</span><span class="p">(</span><span class="s1">&#39;GND&#39;</span><span class="p">)</span>  <span class="c1"># Connect the emitter to ground.</span>

<span class="o">...</span>

<span class="n">q_npn</span><span class="p">[</span><span class="s1">&#39;B&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in1</span>  <span class="c1"># Connect an input to the base.</span>

<span class="o">...</span>

<span class="n">q_npn</span><span class="p">[</span><span class="s1">&#39;C&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">out1</span>  <span class="c1"># Connect the output to the collector.</span>
</code></pre></div>

<p>Another issue is that you can pass a part instance as an argument to a subcircuit that
connects it to the internal circuitry.
But you can't do the same thing with a subcircuit function without making changes to the
code because of the syntactic differences in how connections are made:</p>
<div class="highlight"><pre><span></span><code><span class="nd">@subcircuit</span>
<span class="k">def</span> <span class="nf">analog_average</span><span class="p">(</span><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span><span class="p">,</span> <span class="n">r</span><span class="p">):</span>
<span class="w">    </span><span class="sd">&quot;&quot;&quot;Output the average of the two inputs.&quot;&quot;&quot;</span>

    <span class="n">r1</span><span class="p">,</span> <span class="n">r2</span> <span class="o">=</span> <span class="n">r</span><span class="p">(</span><span class="n">num_copies</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>  <span class="c1"># Create two copies of the resistor part.</span>
    <span class="n">r1</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in1</span><span class="p">,</span> <span class="n">avg</span>
    <span class="n">r2</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span>

    <span class="c1"># If r was a subcircuit function, this would have to be written as:</span>
    <span class="c1"># r(in1, avg)</span>
    <span class="c1"># r(in2, avg)</span>
</code></pre></div>

<p>To make subcircuits act more like parts, the <code>@package</code> decorator has been introduced.
Just replace the <code>@subcircuit</code> decorator while keeping everything else the same:</p>
<div class="highlight"><pre><span></span><code><span class="nd">@package</span>
<span class="k">def</span> <span class="nf">analog_average</span><span class="p">(</span><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span><span class="p">):</span>
    <span class="n">r1</span><span class="p">,</span> <span class="n">r2</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">Part</span><span class="p">(</span><span class="s1">&#39;Device&#39;</span><span class="p">,</span> <span class="s1">&#39;R&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;1K&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>
    <span class="n">r1</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in1</span><span class="p">,</span> <span class="n">avg</span>
    <span class="n">r2</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span>
</code></pre></div>

<p>Instantiating the subcircuit now occurs in two phases.
First, create instances of the subcircuit wherever they are needed:</p>
<div class="highlight"><pre><span></span><code><span class="n">avg1</span> <span class="o">=</span> <span class="n">analog_average</span><span class="p">()</span>

<span class="o">...</span>

<span class="n">avg2</span> <span class="o">=</span> <span class="n">analog_average</span><span class="p">()</span>
</code></pre></div>

<p>In the second phase, make connections to these subcircuits as if they were parts
with the names of the function parameters serving as pin names:</p>
<div class="highlight"><pre><span></span><code><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">in3</span><span class="p">,</span> <span class="n">in4</span><span class="p">,</span> <span class="n">out1</span><span class="p">,</span> <span class="n">out2</span> <span class="o">=</span> <span class="n">Net</span><span class="p">()</span><span class="o">*</span><span class="mi">6</span>

<span class="c1"># Make connections. You can use either [] or . to reference the I/O.</span>
<span class="n">avg1</span><span class="p">[</span><span class="s1">&#39;in1&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in1</span>
<span class="n">avg1</span><span class="o">.</span><span class="n">in2</span>    <span class="o">+=</span> <span class="n">in2</span>
<span class="n">avg1</span><span class="p">[</span><span class="s1">&#39;avg&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">out1</span>

<span class="o">...</span>

<span class="n">avg2</span><span class="p">[</span><span class="s1">&#39;in1&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in3</span>
<span class="n">avg2</span><span class="p">[</span><span class="s1">&#39;in2&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in4</span>
<span class="n">avg2</span><span class="o">.</span><span class="n">avg</span>    <span class="o">+=</span> <span class="n">out2</span>
</code></pre></div>

<p>In addition to nets, pins, and buses, you can pass any other type of
parameter to subcircuits.
For example, <code>analog_average</code> could take a float as a <code>ratio</code> parameter to
set the amount each input contributes to the output:</p>
<div class="highlight"><pre><span></span><code><span class="nd">@package</span>
<span class="k">def</span> <span class="nf">analog_average</span><span class="p">(</span><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span><span class="p">,</span> <span class="n">ratio</span><span class="p">):</span>
    <span class="n">r</span> <span class="o">=</span> <span class="n">Part</span><span class="p">(</span><span class="s1">&#39;Device&#39;</span><span class="p">,</span> <span class="s1">&#39;R&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>
    <span class="n">r1</span> <span class="o">=</span> <span class="n">r</span><span class="p">(</span><span class="n">value</span><span class="o">=</span><span class="mi">2000</span> <span class="o">*</span> <span class="n">ratio</span><span class="p">)</span>
    <span class="n">r2</span> <span class="o">=</span> <span class="n">r</span><span class="p">(</span><span class="n">value</span><span class="o">=</span><span class="mi">2000</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">ratio</span><span class="p">))</span>

    <span class="n">r1</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in1</span><span class="p">,</span> <span class="n">avg</span>
    <span class="n">r2</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span>
</code></pre></div>

<p>Then the subcircuit can either be instantiated with a given ratio:</p>
<div class="highlight"><pre><span></span><code><span class="n">avg1</span> <span class="o">=</span> <span class="n">analog_average</span><span class="p">(</span><span class="n">ratio</span><span class="o">=</span><span class="mf">0.25</span><span class="p">)</span>
<span class="n">avg1</span><span class="o">.</span><span class="n">in1</span> <span class="o">+=</span> <span class="n">in1</span>
<span class="n">avg1</span><span class="o">.</span><span class="n">in2</span> <span class="o">+=</span> <span class="n">in2</span>
<span class="n">avg1</span><span class="o">.</span><span class="n">avg</span> <span class="o">+=</span> <span class="n">out1</span>
</code></pre></div>

<p>or you can set the ratio outside the function call:</p>
<div class="highlight"><pre><span></span><code><span class="n">avg2</span> <span class="o">=</span> <span class="n">analog_average</span><span class="p">()</span>
<span class="n">avg2</span><span class="o">.</span><span class="n">ratio</span> <span class="o">=</span> <span class="mf">0.25</span>  <span class="c1"># Use a normal assignment (=) since this is not a circuit connection.</span>
<span class="n">avg2</span><span class="o">.</span><span class="n">in1</span> <span class="o">+=</span> <span class="n">in3</span>
<span class="n">avg2</span><span class="o">.</span><span class="n">in2</span> <span class="o">+=</span> <span class="n">in4</span>
<span class="n">avg2</span><span class="o">.</span><span class="n">avg</span> <span class="o">+=</span> <span class="n">out2</span>
</code></pre></div>

<p>A subcircuit function instantiates its circuitry when it is called.
But this doesn't happen when using a package.
Instead, the subcircuit is placed in a list and executed after the
complete circuit is finalized
(i.e., whenever <code>ERC()</code> or <code>generate_netlist()</code> is called).
The arguments passed to the function consist of the connections
and other values that were assigned to the package parameters in the preceding code.</p>
<p>That's about it for the <code>@package</code> decorator.
Since it's new, it hasn't seen a lot of use and there could be unknown bugs
lying in wait.
If you have questions or problems, please ask on the
<a href="https://skidl.discourse.group/">SKiDL forum</a> or
raise an <a href="https://github.com/devbisme/skidl/issues">issue</a>. </p>
		</div> <!--/#entry-content-->
	</div> <!--/#main-->
</div>  <!--/#post-->

		</div>

		<div id="footer">
			<p> </p>
		</div><!-- /#footer -->
	</div><!-- /#container -->
	<div style="display:none"></div>
</body>
</html>